package com.example.controller;

import com.example.model.FileInfo;
import com.example.model.Key;
import com.example.util.AesForFile;
import com.example.util.RSAUtil;
import com.example.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;

/**
 * Client端的控制器，主要是调用Server端的接口
 */
@Controller
public class FileController {
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 查询信息
     * @param map
     * @return
     */
    @GetMapping("/listFileInfo")
    public String listFileInfo(Map<String, Object> map) {
        String url = "http://127.0.0.1:8090/listFileInfo";
        HttpEntity<String> httpEntity = new HttpEntity<>(null, setHeaders());
        ResponseEntity<FileInfo[]> exchange = restTemplate.exchange(url, HttpMethod.GET, httpEntity, FileInfo[].class);
        FileInfo[] fileInfos = exchange.getBody();
        List<FileInfo> listFileInfo = Arrays.asList(fileInfos);
        map.put("fileInfos", listFileInfo);
        return "list";
    }

    /**
     * 上传文件
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file) throws Exception {
        String url = "http://127.0.0.1:8090/upload";
        String fileName = file.getOriginalFilename(); // name
        String tempFilePath = System.getProperty("java.io.tmpdir") + file.getOriginalFilename();
        File tempFile = new File(tempFilePath);
        // 生成临时文件
        file.transferTo(tempFile);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(param, setHeaders());

        // MultipartFile 直接转 fileSystemResource 是不行的
        //把临时文件变成FileSystemResource
        FileSystemResource resource = new FileSystemResource(tempFilePath);
        param.add("file", resource);
        restTemplate.postForObject(url, httpEntity, String.class);
        return "success";
    }

    /**
     * 下载文件
     * @param uuid
     * @param originName
     * @param signature
     * @param response
     * @throws Exception
     */
    @GetMapping("/download")
    public void uploadFile(@RequestParam("uuid") String uuid, @RequestParam("originName") String originName, @RequestParam("signature") String signature, HttpServletResponse response) throws Exception {
        // 1 拿到数字信封 对数字信封进行解密(RSA私钥)
        byte[] decode = Base64.getDecoder().decode(signature.getBytes());
        byte[] decodeString = RSAUtil.privateDecrypt(decode, RSAUtil.string2PrivateKey(Key.privateKey));
        String aesRule = new String(decodeString, StandardCharsets.UTF_8);
        byte[] aesDecode = Base64.getDecoder().decode(aesRule.getBytes());
        // 将字符串(aesRule)转回AES密钥
        SecretKeySpec key = new SecretKeySpec(aesDecode, "AES");

        String url = "http://127.0.0.1:8090/download?uuid=" + uuid;
        HttpEntity<byte[]> httpEntity = new HttpEntity(setHeaders());
        ResponseEntity<byte[]> result = restTemplate.exchange(url, HttpMethod.GET, httpEntity, byte[].class);
        // 下载过来的原始bytes
        byte[] originFileBytes = result.getBody();
        String s = new String(originFileBytes);

        response.setHeader("content-disposition", "attachment;filename=" + originName);
        ServletOutputStream os = response.getOutputStream();
        // 下载文件
        AesForFile.decryptedFile(originFileBytes, os, key);
    }

    /**
     * 设置请求头，用私钥进行签名
     *
     * @return
     */
    public HttpHeaders setHeaders() {
        HttpHeaders requestHeaders = new HttpHeaders();
        String xSid = StringUtil.getRandomString(10);
        requestHeaders.add("X-SID", xSid);
        String XSignature = null;
        try {
            XSignature = RSAUtil.sign(xSid, RSAUtil.string2PrivateKey(Key.privateKey));
        } catch (Exception e) {
            e.printStackTrace();
        }
        requestHeaders.add("X-Signature", XSignature);
        return requestHeaders;
    }
}
